/*
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.p4eclipse.core;

import java.util.ArrayList;
import java.util.List;

import net.sourceforge.p4eclipse.core.syncinfo.ResourceSyncInfo;
import net.sourceforge.p4eclipse.ui.PerforceUIPlugin;
import net.sourceforge.p4eclipse.ui.dialogs.ConfirmationDialog;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFileModificationValidator;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;

/**
  * @version 	1.0
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class PerforceFileModificationValidator 
	implements IFileModificationValidator
{
	private PerforceRepositoryProvider provider;
	
	PerforceFileModificationValidator(PerforceRepositoryProvider provider)
	{
		this.provider = provider;
	}	

	private IFile[] filesToCheckout(IFile[] files)
	{
		List list = new ArrayList();
		for (int i=0; i<files.length; i++)
		{
			if (provider.hasRemote(files[i]))
			{
				if (!provider.isCheckedOut(files[i]))
				{
					list.add(files[i]);
				}
			}
		}
		
		return (IFile[])list.toArray(new IFile[0]);
	}

	/*
	 * @see IFileModificationValidator#validateEdit(IFile[], Object)
	 */
	public IStatus validateEdit(IFile[] files, Object context)
	{
		try
		{
			provider.refreshState(files, IResource.DEPTH_ZERO, new NullProgressMonitor());
			
			files = filesToCheckout(files);
			if (files.length > 0)
			{
				if (promptForCheckout(context, files))
				{
					return new Status(IStatus.ERROR, PerforceUIPlugin.ID, IStatus.ERROR, "", null);						
				}

				provider.checkout(files, IResource.DEPTH_ZERO, new NullProgressMonitor());
			}
			
			return new Status(IStatus.OK, PerforceUIPlugin.ID, IStatus.OK, "", null);
		}
		catch (PerforceException e)
		{
			return e.getStatus();
		}
		catch (TeamException e)
		{
			return e.getStatus();
		}
	}
	
	private boolean promptForCheckout(Object context, final IFile[] files)
		throws PerforceException
	{		
		final String message =
			"The system has indicated that one or more files not currently " +
			"opened for edit need to be changed. Do you want them to be " +
			"opened for edit?";
				
		final Shell shell = (Shell)context;				
		Display display = (shell != null) ? shell.getDisplay() : Display.getDefault();
		
		final boolean[] pressedCancel = { true };
		display.syncExec(new Runnable()
		{
			public void run()
			{				
				pressedCancel[0] = !ConfirmationDialog.openConfirmation(shell, "Open for Edit", message, files);
			}
		});
		
		return pressedCancel[0];
	}

	/*
	 * @see IFileModificationValidator#validateSave(IFile)
	 */
	public IStatus validateSave(IFile file)
	{
		IStatus result = new Status(IStatus.OK, PerforceUIPlugin.ID, IStatus.OK, "", null);
		if (provider.hasRemote(file))
		{
			try 
			{
				if (!provider.isCheckedOut(file))
					provider.checkout(new IResource[] { file }, IResource.DEPTH_ZERO, new NullProgressMonitor());
			} 
			catch(TeamException e) 
			{
				result = e.getStatus();
			}
		}
		
		return result;
	}
}
